package com.flying.rsocket;

import io.rsocket.Payload;
import io.rsocket.util.DefaultPayload;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import reactor.core.publisher.Flux;

import java.util.List;

import static com.flying.rsocket.Constants.SHOT_COUNT;

@Slf4j
public class GameController implements Publisher<Payload> {
    private String playerName;
    private final List<Long> shots;
    private Subscriber<? super Payload> subscriber;
    private boolean truce = false;

    public GameController(String playerName) {
        this.playerName = playerName;
        this.shots = generateShots();
    }

    private List<Long> generateShots() {
        return Flux.range(1, SHOT_COUNT)
                .map(x -> (long) Math.ceil(Math.random() * 1000))
                .collectList()
                .block();
    }

    @Override
    public void subscribe(Subscriber<? super Payload> s) {
        this.subscriber = s;
        fireAtWill();
    }

    private void fireAtWill() {
        new Thread(() -> {
            for (Long shotDelay : shots) {
                try {
                    Thread.sleep(shotDelay);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (truce) break;
                log.info("{}:bang!", playerName);
                subscriber.onNext(DefaultPayload.create("bang!"));
            }
            subscriber.onComplete();
        }).start();
    }

    public void processPayload(Payload payload) {
        String message = payload.getDataUtf8();
        switch (message) {
            case "bang!":
                String result = Math.random() < 0.5 ? "Haha missed" : "Own!";
                log.info("{}:{}", playerName, result);
                break;
            case "I give up":
                truce = true;
                log.info("{}:OK, truce", playerName);
                break;
        }
    }
}